using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CompanyX.Insurance.La.ServiceContracts;
using CompanyX.Insurance.La.DataContracts;
using CompanyX.Insurance.La.FaultContracts;

namespace CompanyX.Insurance.La.ServiceProviders
{
    /// <summary>
    /// This is a sample implementation.  Provider for ProducerLicensingAndApplointments server.  
    /// </summary>
    public class ProducerLicensingAndAppointmentsBL
    {
        public TXLifeResponse GetProducerLicensingDetails(TXLifeRequest rq)
        {
            // Create a TxLifeResponse based on the incoming TxLifeRequest. 
            // Constructor automatically copies GUID and all other data that the
            // ACORD spec says must always be echoed, and sets required dates/times to Now. 

            TXLifeResponse rs = new TXLifeResponse();

            // If the main transaction isn't a 228, or the subtransaction a 22810,
            // then this request has been sent to the wrong place. Return an 
            // error code saying that.

            if (rq.TransType.tc != (int)OLI_LU_TRANS_TYPE_CODES_TC._228 || rq.TransSubType.tc != (int)TRANS_SUBTYPE_CODES_TC._22810)
            {
                rs.TransResult.ResultCode.tc = (int) RESULT_CODES_TC._5;
                ResultInfo info = new ResultInfo();
                info.ResultInfoCode.tc = (int) RESULT_INFO_CODES_TC._100;
                info.ResultInfoCode.Value = "Transaction not supported by this service";
                rs.TransResult.ResultInfo.Add(info);
                return rs;
            }

            // Since we got here, we have a good transaction type. Unpack the data that we
            // need to pass to the business logic layer, and make sure that we have the right
            // types and numbers

            // First, fetch the data that we were sent by the client.
            // There should be just one party and one holding in the OLifE. 
            // For the purposes of this example, we will ignore the error case of multiple
            // parties/holdings.

            Party party = rq.OLifE.Party.Count > 0 ? rq.OLifE.Party[0] : null;
            Holding holding = rq.OLifE.Holding.Count > 0 ? rq.OLifE.Holding[0] : null;

            // If we couldn't find either one of them, return with an error code

            if (party == null || holding == null)
            {
                rs.TransResult.ResultCode.tc = (int) RESULT_CODES_TC._5;
                ResultInfo info = new ResultInfo();
                info.ResultInfoCode.tc = (int) RESULT_INFO_CODES_TC._200;
                if (party == null) info.ResultInfoCode.Value = "No Party Supplied";
                if (holding == null) info.ResultInfoCode.Value = "No Holding Supplied";
                rs.TransResult.ResultInfo.Add(info);       
                return rs;
            }

            // Since we got here, we know that we have the data objects that we need to 
            // answer the question. Delegate to a business logic object, which we can
            // replace with a mock for testing/development

            CanAgentSell(rs.TransResult, party, holding);

            // Finished with requests, return the TxLifeResponse packet

            return rs;
        }

        private void CanAgentSell(TransResult rs, Party party, Holding holding)
        {

            // Check the agent's name. If it begins with 'A', he doesn't have a current carrier appointment.
            // Create the error and return it.

            if (party.FullName.StartsWith("A"))
            {
                rs.ResultCode.tc = (int) RESULT_CODES_TC._2;
                rs.ResultCode.Value = "Success with Info";
                ResultInfo info = new ResultInfo();
                info.ResultInfoCode.tc = (int)RESULT_INFO_CODES_TC._4060;
                info.ResultInfoCode.Value = "Can't sell -- no carrier appointment found";
                rs.ResultInfo.Add(info);
                return;
            }

            // Otherwise check his jurisdiction. If it's in Alabama, he's good, otherwise he's
            // not licensed in that state. Create the error and return it.

            Policy policy = holding.Policy;

            if (policy.ApplicationInfo.ApplicationJurisdiction.tc != (int)OLI_LU_STATE_TC._1) // this is Alabama, first on the US list
            {
                rs.ResultCode.tc = (int)RESULT_CODES_TC._2;
                rs.ResultCode.Value = "Success with Info";
                ResultInfo info = new ResultInfo();
                info.ResultInfoCode.tc = (int)RESULT_INFO_CODES_TC._4070;
                info.ResultInfoCode.Value = "Can't sell -- no license found";
                rs.ResultInfo.Add(info);
                return;
            }

            // Check his line of business. If it's life, that's good.  

            if (holding.Policy.LineOfBusiness.tc != (int)OLI_LU_LINEBUS_TC._1)
            {
                // If it's long-term care insurance, fake an unavailable back office system

                if (holding.Policy.LineOfBusiness.tc == (int)OLI_LU_LINEBUS_TC._5)
                {
                    rs.ResultCode.tc = (int)RESULT_CODES_TC._5;
                    rs.ResultCode.Value = "Failure";
                    ResultInfo info = new ResultInfo();
                    info.ResultInfoCode.tc = (int)RESULT_INFO_CODES_TC._300;
                    info.ResultInfoCode.Value = "Back office system not available, sorry";
                    rs.ResultInfo.Add(info);
                    return;
                }
                else
                {
                    // Any other LOB, Create error object and return it. 

                    rs.ResultCode.tc = (int)RESULT_CODES_TC._2;
                    rs.ResultCode.Value = "Success with Info";
                    ResultInfo info = new ResultInfo();
                    info.ResultInfoCode.tc = (int)RESULT_INFO_CODES_TC._4070;
                    info.ResultInfoCode.Value = "Can't sell -- not licensed for this line of business";
                    rs.ResultInfo.Add(info);
                    return;
                }
            }

            // Getting here means that everything is hunky-dory (now where the hell does the expression 
            // come from, and why does it mean 'good'?) Create the Success object and return it. 

            rs.ResultCode.tc = (int)RESULT_CODES_TC._2;
            rs.ResultCode.Value = "Success with Info";
            ResultInfo info1 = new ResultInfo();
            info1.ResultInfoCode.tc = (int)RESULT_INFO_CODES_TC._4000;
            info1.ResultInfoCode.Value = "Agent Can Sell";
            rs.ResultInfo.Add(info1);
            return;
        }
    }
}